/* FINCoS Framework
 * Copyright (C) 2013 CISUC, University of Coimbra
 *
 * Licensed under the terms of The GNU General Public License, Version 2.
 * A copy of the License has been included with this distribution in the
 * fincos-license.txt file.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version. This program is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU General Public License for more details.
 */


package pt.uc.dei.fincos.controller.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map.Entry;

import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

import pt.uc.dei.fincos.basic.Datatype;
import pt.uc.dei.fincos.basic.PredefinedListDomain;

/**
 *
 * GUI for configuring predefined-list domains.
 *
 * @author  Marcelo R.N. Mendes
 *
 */
public final class PredefinedListDomainPanel extends javax.swing.JPanel {

    /** serial id. */
    private static final long serialVersionUID = 4610659214847612111L;

    /** Creates new form PredefinedListDomainPanel. */
    public PredefinedListDomainPanel() {
        initComponents();
        addListeners();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        itemsTable = new javax.swing.JTable();
        addBtn = new javax.swing.JButton();
        deleteBtn = new javax.swing.JButton();
        sameFreqCheck = new javax.swing.JCheckBox();

        setMaximumSize(new java.awt.Dimension(266, 211));
        setMinimumSize(new java.awt.Dimension(266, 211));
        setPreferredSize(new java.awt.Dimension(266, 211));

        itemsTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null}
            },
            new String [] {
                "Item", "Frequency"
            }
        ));
        jScrollPane1.setViewportView(itemsTable);

        addBtn.setText("+");

        deleteBtn.setText("-");

        sameFreqCheck.setText("Deterministic (items have same frequency)");
        sameFreqCheck.setToolTipText("Items are generated in a predictable and repeatable order.");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 204, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(addBtn, javax.swing.GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE)
                    .addComponent(deleteBtn, javax.swing.GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE))
                .addGap(5, 5, 5))
            .addGroup(layout.createSequentialGroup()
                .addComponent(sameFreqCheck)
                .addContainerGap(37, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 166, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(addBtn)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(deleteBtn)))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(sameFreqCheck)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void addListeners() {
        addBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DefaultTableModel model = (DefaultTableModel) itemsTable.getModel();
                model.addRow(new Object[]{null, null});
                itemsTable.changeSelection(model.getRowCount() - 1, 0, false, false);
                itemsTable.editCellAt(model.getRowCount() - 1, 0);
            }

        });

        deleteBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                int selected = itemsTable.getSelectedRow();
                if (selected > -1) {
                    ((DefaultTableModel) itemsTable.getModel()).removeRow(selected);
                } else {
                    JOptionPane.showMessageDialog(null, "Select an item to delete");
                }
            }

        });
    }

    /**
     * Fills the UI with the parameters of the column being configured.
     *
     * @param datatype  the data type of the column
     * @param domain    the domain of the column
     */
    public void fillProperties(Datatype datatype, PredefinedListDomain domain) {
        sameFreqCheck.setSelected(domain.isDeterministic());

        DefaultTableModel model = (DefaultTableModel) itemsTable.getModel();

        // Clears the table
        int rowCount = model.getRowCount();
        for (int i = 0; i < rowCount; i++) {
            model.removeRow(0);
        }


        if (domain.isDeterministic()) {
            for (Object item : domain.getItems()) {
                model.addRow(new Object[]{item, "1.0"});
            }
        } else {
            for (Entry<Object, Double> e : domain.getItemMix().entrySet()) {
                model.addRow(new Object[]{e.getKey(), Double.toString(e.getValue())});
            }

        }

        if (datatype == Datatype.BOOLEAN) {
            addBtn.setEnabled(false);
            deleteBtn.setEnabled(false);
        }
    }

    /**
     * Checks if the fields in the UI have been correctly filled.
     *
     * @param dataType  the data type of the column
     *
     * @return  <tt>true</tt> if all the parameters have been correctly filled,
     *          <tt>false</tt> otherwise
     *
     * @throws Exception  for customized error messages
     *
     */
    protected boolean validateFields(String dataType) throws Exception {
        DefaultTableModel model = (DefaultTableModel) itemsTable.getModel();
        if (model.getRowCount() < 1) {
            return false;
        } else {
            String item;
            for (int i = 0; i < model.getRowCount(); i++) {
                item = (String) model.getValueAt(i, 0);
                if (item == null || item.isEmpty()
                 || (!sameFreqCheck.isSelected()
                  && (model.getValueAt(i, 1) == null
                   || model.getValueAt(i, 1).equals("")))) {
                    throw new Exception("Invalid frequency. (row " + (i + 1) + ").");
                }

                String type = "datatype";
                try {
                    if (dataType.equals("BOOLEAN")) {
                        if (item.equalsIgnoreCase("True")
                                || item.equalsIgnoreCase("Yes")
                                || item.equalsIgnoreCase("1")) {
                            model.setValueAt("true", i, 0);
                        } else if (item.equalsIgnoreCase("False")
                                || item.equalsIgnoreCase("No")
                                || item.equalsIgnoreCase("0")) {
                            model.setValueAt("false", i, 0);
                        } else {
                            throw new Exception("\"" + item
                                             + "\" is not a valid BOOLEAN. (row "
                                             + (i + 1) + ").");
                        }
                    }
                    if (dataType.equals("DOUBLE")) {
                        type = "DOUBLE";
                        Double.parseDouble(item);
                    } else if (dataType.equals("FLOAT")) {
                        type = "FLOAT";
                        Float.parseFloat(item);
                    } else if (dataType.equals("INTEGER")) {
                        type = "INTEGER";
                        Integer.parseInt(item);
                    } else if (dataType.equals("LONG")) {
                        type = "LONG";
                        Long.parseLong(item);
                    } else if (dataType.equals("TIMESTAMP")) {
                        type = "TIMESTAMP";
                        Long.parseLong(item);
                    }
                } catch (NumberFormatException nfe) {
                    throw new Exception("\"" + item + "\" is not a valid " + type
                            + ". (row " + (i + 1) + ").");
                }
            }
            return true;
        }
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    protected javax.swing.JButton addBtn;
    protected javax.swing.JButton deleteBtn;
    protected javax.swing.JTable itemsTable;
    private javax.swing.JScrollPane jScrollPane1;
    protected javax.swing.JCheckBox sameFreqCheck;
    // End of variables declaration//GEN-END:variables
}
